package io.scnb.lesson002.demo17;

import io.scnb.lesson002.demo17.module1.Module1Config;
import io.scnb.lesson002.demo17.module2.Module2Config;
import io.scnb.lesson002.demo17.module2.Service3;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;
import java.util.Map;

public class ParentFactoryTest {
    
    @Test
    public void test1() {
        // 定义容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册bean
        context.registerBean(Module1Config.class, Module2Config.class);
        // 启动容器
        context.refresh();
    }

    @Test
    public void test2() {
        // 创建父容器
        AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
        // 向父容器中注入Module1Config类
        parentContext.registerBean(Module1Config.class);
        // 启动父容器
        parentContext.refresh();
        
        // 创建子容器
        AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
        // 向父容器中注入Module2Config类
        childContext.registerBean(Module2Config.class);
        // 给子容器设置父容器
        childContext.setParent(parentContext);
        // 启动父容器
        childContext.refresh();
        
        // 从子容器中获取Service3
        Service3 service3 = (Service3) childContext.getBean("service3");
        System.out.println(service3.m1());
        System.out.println(service3.m2());
    }

    /**
     * BeanFactory#getBean支持容器嵌套结构查找
     * ListableBeanFactory#getBeanNamesForType不支持容器嵌套查找，只能找到当前容器中符合条件的bean
     */
    @Test
    public void test3() {
        // 创建父容器
        DefaultListableBeanFactory parentFactory = new DefaultListableBeanFactory();
        // 向父容器中注册一个bean
        parentFactory.registerBeanDefinition("userName",
                BeanDefinitionBuilder.genericBeanDefinition(String.class).addConstructorArgValue("scnb").getBeanDefinition());

        //创建一个子容器childFactory
        DefaultListableBeanFactory childFactory = new DefaultListableBeanFactory();
        //调用setParentBeanFactory指定父容器
        childFactory.setParentBeanFactory(parentFactory);
        //向子容器parentFactory注册一个bean[address->"上海"]
        childFactory.registerBeanDefinition("address",
                BeanDefinitionBuilder.
                        genericBeanDefinition(String.class).
                        addConstructorArgValue("上海").
                        getBeanDefinition());
        System.out.println("获取bean【userName】：" + childFactory.getBean("userName"));//@1

        System.out.println(Arrays.asList(parentFactory.getBeanNamesForType(String.class)));
        System.out.println(Arrays.asList(childFactory.getBeanNamesForType(String.class)));
    }

    /**
     * 使用BeanFactoryUtils中的带有Ancestors的方法，就可以进行容器的层次查找了
     */
    @Test
    public void test4() {
        // 创建父容器
        DefaultListableBeanFactory parentFactory = new DefaultListableBeanFactory();
        // 向父容器中注册一个bean
        parentFactory.registerBeanDefinition("userName",
                BeanDefinitionBuilder.genericBeanDefinition(String.class).addConstructorArgValue("scnb").getBeanDefinition());

        //创建一个子容器childFactory
        DefaultListableBeanFactory childFactory = new DefaultListableBeanFactory();
        //调用setParentBeanFactory指定父容器
        childFactory.setParentBeanFactory(parentFactory);
        //向子容器parentFactory注册一个bean[address->"上海"]
        childFactory.registerBeanDefinition("address",
                BeanDefinitionBuilder.
                        genericBeanDefinition(String.class).
                        addConstructorArgValue("上海").
                        getBeanDefinition());
        System.out.println("获取bean【userName】：" + childFactory.getBean("userName"));//@1

        //层次查找所有符合类型的bean名称
        String[] beanNamesForTypeIncludingAncestors = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(childFactory, String.class);
        System.out.println(Arrays.asList(beanNamesForTypeIncludingAncestors));
        Map<String, String> beansOfTypeIncludingAncestors = BeanFactoryUtils.beansOfTypeIncludingAncestors(childFactory, String.class);
        System.out.println(Arrays.asList(beansOfTypeIncludingAncestors));
    }
}
